
#include "task.hpp"

#include <iostream>
#include <vector>
#include <utility>
#include<sys/wait.h>
#include<sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>

using namespace std;

#define PROCESS_NUM 5

int waitTask(int pipefd, bool& quit)
{
    uint32_t taskid = 0;
    int ret = read(pipefd,&taskid, sizeof(taskid));
    if(ret == 0)
    {
        quit = true;
        return -1;
    }
    return taskid;
}

void sentAndWakeup(pid_t childpid, int pipefd, uint32_t taskid)
{

    write(pipefd,&taskid,sizeof(taskid));
    printf("father process: %d, call child procees:%d,to excute task: %s, from pipe:%d\n",getpid(),childpid,desc[taskid].c_str(),pipefd);
}

int main()
{
    Load();// 加载任务
    vector<pair<pid_t, int>> slots; // 记录子进程pid+打开的匿名管道

    // 创建子进程，建立父子间的通信管道
    for (int i = 0; i < PROCESS_NUM; ++i)
    {
        // 创建匿名管道
        int pipefd[2];
        int ret = pipe(pipefd);
        assert(ret != -1);
        (void)ret;

        // 创建子进程
        int pid = fork();
        if (pid == 0)
        {
            while (true)
            {
                // 等待父进程传入任务序号
                bool quit = false;
                int taskid = waitTask(pipefd[0], quit);
                if (quit)
                    break;
                if (taskid >= 0 && taskid < TaskNumber())
                {
                    printf("child process:%d, had a pipe:%d, execute taskid:%d\n",getpid(),pipefd[0],taskid);
                    callTasks[taskid];
                }
                else
                {
                    cout << "child, get command error:" << taskid << endl;
                }
            }
            close(pipefd[0]);
            exit(1);
        }
        // 父进程
        close(pipefd[0]);
        slots.push_back(make_pair(pid, pipefd[1]));
    }
    // 派遣任务
    srand((unsigned int)time(nullptr)*getpid());
    while(true)
    {
        //要派遣的任务编号
        int taskid = rand()%TaskNumber();
        //要派遣的进程pid
        int child = rand()%slots.size();
        //分发任务
        sentAndWakeup(slots[child].first, slots[child].second, taskid);
        sleep(1);
    }
    //结束
    for(const auto& it : slots)
    {
        close(it.second);
    }
    for(const auto& it: slots)
    {
        waitpid(it.first,nullptr,0);
    }
    return 0;
}